import { formidable } from 'formidable';
import fs from 'fs';
import path from 'path';
import { createWorker } from 'tesseract.js';
import { v4 as uuidv4 } from 'uuid';

// 配置Tesseract.js语言包缓存路径
const LANG_PATH = path.join(process.cwd(), 'public', 'tessdata');
// 使用CDN地址
const LANG_CDN = 'https://tessdata.projectnaptha.com/4.0.0';

// 确保语言包目录存在
try {
  if (!fs.existsSync(LANG_PATH)) {
    fs.mkdirSync(LANG_PATH, { recursive: true });
    console.log(`创建Tesseract语言包目录: ${LANG_PATH}`);
  }
} catch(error) {
  console.error(`创建语言包目录失败: ${error.message}`);
}

// 检查是否已经有语言包
const checkLanguagePack = (lang) => {
  const langFile = path.join(LANG_PATH, `${lang}.traineddata`);
  return fs.existsSync(langFile);
};

// 已知问题语言包列表
const PROBLEMATIC_LANGS = ['chi_sim', 'chi_tra', 'jpn', 'kor'];

// 如果是调试环境，预热语言包
if (process.env.NODE_ENV === 'development') {
  setTimeout(async () => {
    try {
      const langToPrewarm = 'eng'; // 预热英语语言包
      console.log(`尝试预热语言包: ${langToPrewarm}`);
      
      const tempWorker = await createWorker(langToPrewarm, 0, {
        // 使用CDN设置
        workerBlobURL: false,
        corePath: 'https://cdn.jsdelivr.net/npm/tesseract.js-core@4.0.4/tesseract-core.wasm.js',
        langPath: LANG_CDN,
        gzip: true,
        logger: m => console.log(`预热: ${m.status} ${Math.round(m.progress * 100)}%`)
      });
      
      await tempWorker.terminate();
      console.log('语言包预热完成');
    } catch (e) {
      console.error('语言包预热失败:', e);
    }
  }, 1000);
}

// 禁用Next.js的默认body解析，以便我们可以使用formidable处理文件上传
export const config = {
  api: {
    bodyParser: false,
  },
};

/**
 * 解析请求中的文件和字段
 * @param {Object} req - 请求对象
 * @returns {Promise<Object>} - 解析结果
 */
const parseForm = async (req) => {
  return new Promise((resolve, reject) => {
    const options = {
      keepExtensions: true,
      maxFileSize: 5 * 1024 * 1024, // 5MB
    };
    
    const form = formidable(options);

    form.parse(req, (err, fields, files) => {
      if (err) {
        reject(err);
        return;
      }
      resolve({ fields, files });
    });
  });
};

/**
 * 保存上传的图片到临时目录
 * @param {Object} file - 文件对象
 * @returns {Promise<string>} - 保存的路径
 */
const saveImageToTemp = async (file) => {
  // 确保临时目录存在
  const tempDir = path.join(process.cwd(), 'temp');
  if (!fs.existsSync(tempDir)) {
    fs.mkdirSync(tempDir, { recursive: true });
  }

  // 生成唯一文件名
  const originalFilename = file.originalFilename || file.newFilename || 'unknown';
  const fileName = `${uuidv4()}${path.extname(originalFilename)}`;
  const filePath = path.join(tempDir, fileName);

  // 读取上传的文件并保存到临时目录
  const data = fs.readFileSync(file.filepath);
  fs.writeFileSync(filePath, data);
  
  // 尝试删除原始上传的临时文件
  try {
    fs.unlinkSync(file.filepath);
  } catch (error) {
    console.warn('无法删除原始临时文件:', error);
  }

  return filePath;
};

/**
 * 使用简单备用模式，返回固定文本
 * 当Tesseract.js完全无法工作时使用
 */
const fallbackOcr = async () => {
  return `这是OCR备用模式返回的文本。
  
由于系统无法下载或加载OCR语言模型，此功能暂时无法正常工作。
  
您可以尝试以下解决方法：
1. 使用更简单的图片
2. 选择英语(eng)作为识别语言
3. 使用调试模式测试连接
4. 稍后再试
  
技术原因: Tesseract.js无法下载或访问语言模型文件。`;
};

/**
 * 处理OCR图片识别
 * @param {string} imagePath - 图片路径
 * @param {string} language - 识别语言
 * @param {string} mode - 识别模式
 * @returns {Promise<string>} - 识别结果文本
 */
const processOcr = async (imagePath, language, mode) => {
  // 调试模式直接返回测试文本
  if (mode === 'debug') {
    console.log('使用调试模式，直接返回测试文本');
    return '这是测试文本。OCR引擎目前处于调试模式，可以正常连接。';
  }
  
  // 超简单模式，跳过真实OCR处理
  if (mode === 'simple') {
    console.log('使用超简单模式，直接返回模拟结果');
    return `这是来自图片的模拟OCR结果文本。
使用了 ${language} 语言模型和简单模式。
此文本是固定的，不是真实的OCR识别结果。
请使用其他模式获取真实结果。`;
  }
  
  // 确保文件存在
  if (!fs.existsSync(imagePath)) {
    console.error(`图片文件不存在: ${imagePath}`);
    throw new Error('图片文件不存在或无法访问');
  }
  
  // 检查语言包是否存在
  const hasLanguagePack = checkLanguagePack(language);
  console.log(`语言包 ${language} 存在状态: ${hasLanguagePack}`);
  
  // 对于中文识别，添加额外的提示
  if (PROBLEMATIC_LANGS.includes(language) && !hasLanguagePack) {
    console.log(`注意: ${language} 语言可能需要较长时间下载`);
  }
  
  // 如果识别的是中文，但语言包不存在，切换到英语模式进行预处理
  let fallbackToEnglish = false;
  if (language.startsWith('chi_') && !hasLanguagePack && !checkLanguagePack('eng')) {
    console.log('中文语言包不存在，先使用英语预热');
    fallbackToEnglish = true;
  }
  
  let worker = null;
  
  try {
    console.log(`[${new Date().toISOString()}] 开始OCR处理: 语言=${language}, 模式=${mode}, 文件路径=${imagePath}`);
    
    // 检查文件大小
    const fileStats = fs.statSync(imagePath);
    console.log(`文件大小: ${fileStats.size} 字节`);
    
    if (fileStats.size === 0) {
      throw new Error('图片文件为空');
    }
    
    if (fileStats.size > 5 * 1024 * 1024) {
      console.warn('图片文件较大，可能会影响处理速度');
    }
    
    // 读取图片文件为 buffer
    console.log('读取图片文件...');
    const imageBuffer = fs.readFileSync(imagePath);
    console.log(`成功读取图片文件，大小: ${imageBuffer.length} 字节`);
    
    // 设置超时控制，防止无限等待
    const timeout = 60000; // 60秒超时
    let isTimedOut = false;
    const timeoutId = setTimeout(() => {
      isTimedOut = true;
      console.error('OCR处理超时');
      if (worker) {
        try {
          worker.terminate().catch(e => console.error('终止worker失败:', e));
        } catch (e) {
          console.error('终止worker时发生错误:', e);
        }
      }
    }, timeout);
    
    // 如果需要预热，先用英语处理
    if (fallbackToEnglish) {
      try {
        console.log('使用英语预热...');
        const tempWorker = await createWorker('eng', 0, {
          langPath: LANG_PATH,
          logger: m => console.log(`英语预热: ${m.status} ${Math.round(m.progress * 100)}%`)
        });
        await tempWorker.terminate();
        console.log('英语预热完成');
      } catch (warmupError) {
        console.error('英语预热失败:', warmupError);
      }
    }
    
    console.log(`[${new Date().toISOString()}] 创建Tesseract worker...`);
    
    // 创建Tesseract worker
    try {
      // 针对中文识别的优化参数
      const oem = (mode === 'accurate' || language.startsWith('chi_')) ? 1 : 0;
      const psm = language.startsWith('chi_') ? 6 : 3; // 6=假设整块文字，3=自动检测
      
      worker = await createWorker(language, oem, {
        langPath: LANG_PATH,
        cachePath: LANG_PATH,
        // 指定CDN地址，解决下载问题
        workerBlobURL: false,
        corePath: 'https://cdn.jsdelivr.net/npm/tesseract.js-core@4.0.4/tesseract-core.wasm.js',
        // 强制使用CDN语言包
        gzip: true,
        langPath: LANG_CDN,
        logger: progress => {
          console.log(`[${new Date().toISOString()}] OCR进度: ${progress.status} ${Math.round(progress.progress * 100)}%`);
        },
        errorHandler: error => {
          console.error(`[${new Date().toISOString()}] OCR处理中出现错误:`, error);
        }
      });
      
      // 设置额外的识别参数，针对中文优化
      if (language.startsWith('chi_')) {
        await worker.setParameters({
          tessedit_pageseg_mode: psm.toString(),
          preserve_interword_spaces: '1'
        });
        console.log('已设置中文识别优化参数');
      }
      
      console.log(`[${new Date().toISOString()}] Tesseract worker创建成功`);
    } catch (initError) {
      console.error(`[${new Date().toISOString()}] 创建Tesseract worker失败:`, initError);
      clearTimeout(timeoutId);
      throw new Error(`创建OCR引擎失败: ${initError.message}`);
    }
    
    if (isTimedOut) {
      clearTimeout(timeoutId);
      throw new Error('OCR处理超时');
    }
    
    console.log(`[${new Date().toISOString()}] 开始识别文字...`);
    
    // 使用Promise.race来实现超时控制
    const recognizePromise = worker.recognize(imageBuffer);
    const timeoutPromise = new Promise((_, reject) => {
      setTimeout(() => reject(new Error('OCR识别超时')), timeout);
    });
    
    // 进行文字识别 - 新版API
    const result = await Promise.race([recognizePromise, timeoutPromise]);
    
    // 清除超时控制
    clearTimeout(timeoutId);
    
    console.log(`[${new Date().toISOString()}] 文字识别完成`);
    
    // 终止worker
    try {
      console.log(`[${new Date().toISOString()}] 终止Tesseract worker...`);
      await worker.terminate();
      console.log(`[${new Date().toISOString()}] Tesseract worker已终止`);
      worker = null;
    } catch (termError) {
      console.error(`[${new Date().toISOString()}] 终止Tesseract worker失败:`, termError);
    }
    
    if (!result || !result.data || !result.data.text) {
      console.log(`[${new Date().toISOString()}] 识别结果为空`);
      return '';
    }
    
    const text = result.data.text;
    console.log(`[${new Date().toISOString()}] 识别结果: ${text.substring(0, 50)}${text.length > 50 ? '...' : ''}`);
    return text;
  } catch (error) {
    console.error(`[${new Date().toISOString()}] OCR处理详细错误:`, error);
    
    if (error.stack) {
      console.error(`[${new Date().toISOString()}] 错误堆栈:`, error.stack);
    }
    
    let errorMessage = error.message || '未知错误';
    
    // 检查是否为语言包错误
    const isLangError = errorMessage.includes('Cannot load language') || 
                        errorMessage.includes('Missing language data') ||
                        errorMessage.includes('no such file or directory') ||
                        errorMessage.includes('traineddata');
    
    // 使用备用OCR处理
    if (isLangError) {
      console.log('检测到语言包错误，切换到备用OCR模式');
      return await fallbackOcr();
    }
    
    // 尝试恢复已知的错误情况
    if (isLangError) {
      if (language === 'eng') {
        errorMessage = '无法加载英语语言包，请尝试使用调试模式';
      } else {
        errorMessage = `无法加载所选语言包(${language})，建议先尝试英语(eng)`;
      }
    } else if (errorMessage.includes('timeout') || errorMessage.includes('超时')) {
      errorMessage = 'OCR处理超时，请尝试使用快速模式或上传更小的图片';
    }
    
    throw new Error(`OCR处理失败: ${errorMessage}`);
  } finally {
    // 确保worker被终止
    if (worker) {
      try {
        console.log(`[${new Date().toISOString()}] 在finally块中终止Tesseract worker...`);
        await worker.terminate();
        console.log(`[${new Date().toISOString()}] Tesseract worker已终止`);
      } catch (termError) {
        console.error(`[${new Date().toISOString()}] 在finally块中终止Tesseract worker失败:`, termError);
      }
    }
  }
};

/**
 * 清理临时文件
 * @param {string} filePath - 文件路径
 */
const cleanupTempFile = (filePath) => {
  try {
    if (fs.existsSync(filePath)) {
      fs.unlinkSync(filePath);
    }
  } catch (error) {
    console.error('清理临时文件失败:', error);
  }
};

/**
 * OCR文字识别API处理函数
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
export default async function handler(req, res) {
  // 只允许POST请求
  if (req.method !== 'POST') {
    return res.status(405).json({ success: false, message: '方法不允许' });
  }

  let tempImagePath = null;

  try {
    // 解析上传的表单数据
    const { fields, files } = await parseForm(req);
    
    // 验证是否上传了图片
    const imageFile = files.image?.[0] || files.image;
    if (!imageFile) {
      return res.status(400).json({ success: false, message: '未上传图片' });
    }
    
    // 获取语言和模式参数
    const language = Array.isArray(fields.language) 
      ? fields.language[0] 
      : fields.language || 'chi_sim';
    
    const mode = Array.isArray(fields.mode)
      ? fields.mode[0]
      : fields.mode || 'accurate';
    
    // 保存图片到临时目录
    tempImagePath = await saveImageToTemp(imageFile);
    
    // 调用Tesseract.js进行OCR识别
    const recognizedText = await processOcr(tempImagePath, language, mode);
    
    // 返回识别结果
    res.status(200).json({
      success: true,
      text: recognizedText || '',
    });
  } catch (error) {
    console.error('OCR API错误:', error);
    res.status(500).json({
      success: false,
      message: error.message || 'OCR处理失败'
    });
  } finally {
    // 清理临时文件
    if (tempImagePath) {
      cleanupTempFile(tempImagePath);
    }
  }
} 